﻿// ---------------------------------------------------------------------------------------------
// <copyright file="Cycle.cs" company="Hiyoko">
//   Copyright (c) 2015 All Rights Reserved
// </copyright>
// <summary>
//   This class represents a cycle - used as output.
// </summary>
// ---------------------------------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Hiyoko.DependenciesSorter.CycleDetection
{
    public class Cycle
    {
        #region Properties

        public List<Component> Components { get; private set; }

        #endregion Properties

        #region Constructor

        /// <summary>
        /// Initializes a new instance of the Cycle class.
        /// </summary>
        /// <param name="vertices">The list of vertices</param>
        public Cycle(IEnumerable<Vertex<string>> vertices)
        {
            if (vertices == null)
            {
                throw new ArgumentException("An error occured: the argument <vertices> is null.");
            }

            Components = new List<Component>();
            foreach (var vertex in vertices)
            {
                if (Components.Any(c => c.Name.Equals(vertex.Value)))
                {
                    throw new ApplicationException("An error occured: the vertex is already present in the collection.");
                }

                var component = new Component(vertex);
                Components.Add(component);
            }
        }

        #endregion Constructor

        #region Public methods

        /// <summary>
        /// Removes independent dependencies and self-references.
        /// </summary>
        public void CleanDependencies()
        {
            var componentNames = Components.Select(c => c.Name).ToList();
            foreach (var component in Components)
            {
                var removedDependencies = component.Dependencies.Where(d => !componentNames.Contains(d)).ToList();
                removedDependencies.AddRange(component.Dependencies.Where(d => component.Name.Contains(d)).ToList());
                foreach (var removedDependency in removedDependencies)
                {
                    component.RemoveDependency(removedDependency);
                }
                component.Dependencies.Sort();
            }
            Components = Components.OrderBy(c => c.Name).ToList();
        }

        /// <summary>
        /// Displays object.
        /// </summary>
        public override string ToString()
        {
            var sb = new StringBuilder();
            sb.AppendLine("Cycle:");
            foreach (var component in Components)
            {
                sb.Append(component.ToString());
            }
            return sb.ToString();
        }

        #endregion Public methods
    }
}
